
#include "EWindow.h"
#include "EGraphics.h"
#include "EInputListener.h"
#include "ECanvas.h"
#include <ctime>
#include <unistd.h>

namespace Eyas3D
{
	bool EGameWindow::mQuite = ( false );
	/* -------------------------------------------------------------------------- */
	EGameWindow *EGameWindow::GWindow;
	/* -------------------------------------------------------------------------- */
	/*long EGameWindow::WinProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam )
	{
		if ( !EGameWindow::GWindow )
			return(DefWindowProc( hWnd, Msg, wParam, lParam ) );
		switch ( Msg )
		{
		// 绘制 
		case WM_MOVING:
		case WM_PAINT:
		{
			PAINTSTRUCT	ps;
			HDC		hdc = BeginPaint( hWnd, &ps );
			EGameWindow::GWindow->onPaint( hdc );
			EndPaint( hWnd, &ps );
			break;
		}		
		case WM_TIMER:
		{
			EGameWindow::GWindow->updateWindow();
			break;
		}
		// 键盘按下
		case WM_KEYDOWN:
		{
			break;
		}
		// 键盘释放
		case WM_KEYUP:
		{
			break;
		}
		case WM_MOUSEWHEEL:
		{
			
		}
		// 鼠标移动 
		case WM_MOUSEMOVE:
		{
			
			break;
		}
		// 关闭窗口
		case WM_CLOSE:
		{
			DestroyWindow( hWnd );
			break;
		}
		case WM_DESTROY:
		{
			PostQuitMessage( 0 );
			break;
		}
		default:
			return(DefWindowProc( hWnd, Msg, wParam, lParam ) );
		}
		return(0);
	}*/
	/* -------------------------------------------------------------------------- */
	EGameWindow::EGameWindow( const EString & windowTitle, EGraphics *graphics ) :
		mWindowTitle( windowTitle ), mCanvasListener( NULL ), graphics( graphics )
	{
		if ( !(registerWindow() && createWindow() ) )
		{
			throw "Init Window Failed!";
		}
		mQuite = ( false );
	}
	/* -------------------------------------------------------------------------- */
	EGameWindow::~EGameWindow()
	{
		//DestroyWindow( mHwnd );
		SDL_DestroyWindow( mHwnd );
		for ( InputItr itr = mInputListeners.begin(); itr != mInputListeners.end(); ++itr )
		{
			SafeDelete( *itr );
		}
		SafeDelete( mCanvasListener );
	}
	/* -------------------------------------------------------------------------- */
	/* 显示窗口 */
	void EGameWindow::showWindow( EBool show )
	{
		//::ShowWindow( mHwnd, SW_SHOW );
		//UpdateWindow( mHwnd );
	}
	/* -------------------------------------------------------------------------- */
	void EGameWindow::updateWindow()
	{
		/* 刷心窗口 */
		//::InvalidateRect( mHwnd, NULL, FALSE );
		//::UpdateWindow( mHwnd );
		EGraphics::graphic->fillBuffer( mHwnd );
	}
	/* -------------------------------------------------------------------------- */
	void EGameWindow::setCanvasListener( ECanvas *canvasListener )
	{
		mCanvasListener = canvasListener;
	}
	/* -------------------------------------------------------------------------- */
	void EGameWindow::onUpdate()
	{
		/*
		 * if (mCanvasListener)
		 * {
		 * EGraphics::clearBuffer(EColor(0, 0, 0));
		 * mCanvasListener->update();
		 * mCanvasListener->onPaint();
		 * }
		 */
	}
	/* 窗口绘制函数 */
	void EGameWindow::onPaint( SDL_Window* window )
	{
		//cout<<"onPaint start"<<endl;
		if( mHwnd==NULL )
			return;
		if ( mCanvasListener )
		{
			//
			graphics->clearBuffer( EColor( 0, 0, 0 ) );
			//game
			//窗口刷新前，计算状态
			// scene update．调整位置状态
			mCanvasListener->update();
			//game paint, showHelpInfo()
			mCanvasListener->onPaint();
			//graphics->drawString( "abc", 20, 50, EColor( 255, 0, 0 ) );
			//画到图上
			graphics->fillBuffer( mHwnd );
		}else{
			printf( "mCanvasListener is NULL\n" );
		}
		//cout<<"onPaint end"<<endl;
	}
	/* -------------------------------------------------------------------------- */
	void EGameWindow::addInputListener( EInputListener* listener )
	{
		//添加已经确定好的游戏框架
		mInputListeners.push_back( listener );
	}
	/* -------------------------------------------------------------------------- */
	void EGameWindow::removeInputListener( EInputListener* listener )
	{
		for ( InputItr itr = mInputListeners.begin(); itr != mInputListeners.end(); )
		{
			if ( *itr == listener )
			{
				mInputListeners.erase( itr++ );
			}else
				++itr;
		}
	}
	/* -------------------------------------------------------------------------- */
	void EGameWindow::onKeyDown( EInt msg )
	{
		/* ::MessageBox(0, "Window onKeyDown", 0, 0); */
		for ( InputItr itr = mInputListeners.begin(); itr != mInputListeners.end(); ++itr )
			(*itr)->keyPress( msg );
	}
	/* -------------------------------------------------------------------------- */
	void EGameWindow::onKeyRelease( EInt msg )
	{
		/* ::MessageBox(0, "Window onKeyRelease", 0, 0); */
		for ( InputItr itr = mInputListeners.begin(); itr != mInputListeners.end(); ++itr )
			(*itr)->keyRlease( msg );
	}
	/* -------------------------------------------------------------------------- */
	void EGameWindow::onMousePress( bool rightPress )
	{
		if ( rightPress )
			::SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_INFORMATION, "Window R onMousePress", 0, 0 );
		else
			::SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_INFORMATION, "Window L onMousePress", 0, 0 );
	}
	/* -------------------------------------------------------------------------- */
	void EGameWindow::onMouseMove( EInt x, EInt y )
	{
		/* ::MessageBox(0, "Window onMouseMove", 0, 0); */
		for ( InputItr itr = mInputListeners.begin(); itr != mInputListeners.end(); ++itr )
			(*itr)->mouseMove( x, y );
	}
	/* -------------------------------------------------------------------------- */
	void EGameWindow::onMouseWheel( EInt delta )
	{
		for ( InputItr itr = mInputListeners.begin(); itr != mInputListeners.end(); ++itr )
			(*itr)->mouseWheel( delta );
	}
	void EGameWindow::quiteApplication()
	{
		mQuite = true;
	}
	/* -------------------------------------------------------------------------- */
	void EGameWindow::startLoop()
	{
		SDL_Event myEvent;//事件
		int x,y;	short delta;
		//int quit = 0;
		while ( !mQuite ) //建立事件主循环
		{
			if ( SDL_PollEvent ( &myEvent ) ) //从队列里取出事件
			{
				//获得事件
				switch ( myEvent.type ) //根据事件类型分门别类去处理
				{				
				case SDL_KEYUP:
					switch( myEvent.key.keysym.sym )
					{
						case SDLK_LEFT:
							break;
						case SDLK_RIGHT:
							break;
						case SDLK_UP:
							break;
						case SDLK_SPACE:
							break;
						default:
							break;
					}
					//cout<<myEvent.key.keysym.sym<<endl;
					//printf( "keyup: %d\n", myEvent.key.keysym.sym );
					EGameWindow::GWindow->onKeyRelease( myEvent.key.keysym.sym );
					break;
				case SDL_KEYDOWN:
					//printf( "keydown: %d\n", myEvent.key.keysym.sym );
					EGameWindow::GWindow->onKeyDown( myEvent.key.keysym.sym );
					break;
				case SDL_MOUSEMOTION:
					x	= ( myEvent.motion.x );
					y	= ( myEvent.motion.y );
					EGameWindow::GWindow->onMouseMove( x, y );
					break;
				case SDL_MOUSEWHEEL:
					delta = (short)myEvent.motion.y; /* wheel rotation */
					EGameWindow::GWindow->onMouseWheel( delta * 0.5f / PI );
					break;
				case SDL_MOUSEBUTTONDOWN:
					break;
				case SDL_MOUSEBUTTONUP:
					break;
				case SDL_QUIT://如果是离开事件
					mQuite = true;
					break;
				case SDL_WINDOWEVENT:
					switch (myEvent.window.event) {
					case SDL_WINDOWEVENT_SHOWN:
						SDL_Log("Window %d shown", myEvent.window.windowID);
						break;
					case SDL_WINDOWEVENT_HIDDEN:
						SDL_Log("Window %d hidden", myEvent.window.windowID);
						break;
					case SDL_WINDOWEVENT_EXPOSED:
						EGameWindow::GWindow->onPaint( 0 );
						SDL_Log("Window %d exposed", myEvent.window.windowID);
						break;
					case SDL_WINDOWEVENT_MOVED:
						SDL_Log("Window %d moved to %d,%d",
								myEvent.window.windowID, myEvent.window.data1,
								myEvent.window.data2);
						break;
					case SDL_WINDOWEVENT_RESIZED:
						SDL_Log("Window %d resized to %dx%d",
								myEvent.window.windowID, myEvent.window.data1,
								myEvent.window.data2);
						break;
					case SDL_WINDOWEVENT_SIZE_CHANGED:
						SDL_Log("Window %d size changed to %dx%d",
								myEvent.window.windowID, myEvent.window.data1,
								myEvent.window.data2);
						break;
					case SDL_WINDOWEVENT_MINIMIZED:
						SDL_Log("Window %d minimized", myEvent.window.windowID);
						break;
					case SDL_WINDOWEVENT_MAXIMIZED:
						SDL_Log("Window %d maximized", myEvent.window.windowID);
						break;
					case SDL_WINDOWEVENT_RESTORED:
						SDL_Log("Window %d restored", myEvent.window.windowID);
						break;
					case SDL_WINDOWEVENT_ENTER:
						SDL_Log("Mouse entered window %d",
								myEvent.window.windowID);
						break;
					case SDL_WINDOWEVENT_LEAVE:
						SDL_Log("Mouse left window %d", myEvent.window.windowID);
						break;
					case SDL_WINDOWEVENT_FOCUS_GAINED:
						SDL_Log("Window %d gained keyboard focus",
								myEvent.window.windowID);
						break;
					case SDL_WINDOWEVENT_FOCUS_LOST:
						SDL_Log("Window %d lost keyboard focus",
								myEvent.window.windowID);
						break;
					case SDL_WINDOWEVENT_CLOSE:
						mQuite = true;						
						SDL_Log("Window %d closed", myEvent.window.windowID);
						break;
					default:
						SDL_Log("Window %d got unknown event %d",
								myEvent.window.windowID, myEvent.window.event);
						break;
					}
					//cout<<"SDL_WINDOWEVENT"<<endl;
					break;
				default: // Report an unhandled event, 512, 1025, 1026
					//printf("I don't know what this event is!\n");
					//cout<<myEvent.type<<endl;
					//printf( "unknown event: %d\n", myEvent.type );
					break;
				}
				onUpdate();
			}else{
				//没获得事件
				//::SDL_Delay( 100 );
			}		
			//render
			//一帧一帧渲染
			//撤掉game层
			render();	
		}
		SDL_DestroyWindow ( mHwnd );
		SDL_Quit();
	}
	SDL_TimerID EGameWindow::mTimer;
	Uint32 my_callbackfunc( Uint32 interval, void *param )
	{
		//超多线程退出
		if( !EGameWindow::mQuite ){
		//cout<<"rendering..."<<endl;
			EGameWindow::GWindow->updateWindow();
			EGameWindow::mTimer = SDL_AddTimer( 35, my_callbackfunc, NULL );
		}else{
			cout<<"quit timer..."<<endl;
		}
	}
	void EGameWindow::render()
	{
		EGameWindow::GWindow->updateWindow();
		EGameWindow::GWindow->onPaint( 0 );
	}
	/* -------------------------------------------------------------------------- */
	bool EGameWindow::createWindow()
	{
		mHwnd = SDL_CreateWindow( "Eyas3D",
			SDL_WINDOWPOS_UNDEFINED,           // initial x position
			SDL_WINDOWPOS_UNDEFINED,           // initial y position
			SCREEN_WIDTH, SCREEN_HEIGHT,
			SDL_WINDOW_OPENGL	);
		if ( !mHwnd )
		{
			::SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_INFORMATION, "Create Window Failed", 0, 0 );
			//::MessageBox( 0, "Create Window Failed", 0, 0 );
			return(false);
		}
		/*
		 * RECT clientSize = {CW_USEDEFAULT, CW_USEDEFAULT, SCREEN_WIDTH, SCREEN_HEIGHT};
		 * AdjustWindowRect(&clientSize, WS_OVERLAPPEDWINDOW & (~WS_MAXIMIZEBOX)& (~WS_THICKFRAME), false);
		 */
		//::SetTimer( mHwnd, WM_TIMER, 35, NULL );
		//Uint32 delay = (33 / 10) * 10;  /* To round it down to the nearest 10 ms */
		//mTimer = SDL_AddTimer( 35, my_callbackfunc, NULL );
		/* 手动播种 */
		srand( time( NULL ) );
		return(true);
	}
	/* -------------------------------------------------------------------------- */
	bool EGameWindow::registerWindow()
	{
		return(true);
	}
	/* -------------------------------------------------------------------------- */
}
